/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src.view.gl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import src.domain.gl.Glaccnt;
import src.domain.gl.Jv;
import src.domain.gl.Jvdet;
import src.domain.security.Users;
import src.domain.system.Numbering;
import src.services.CRUEDService;
import src.services.gl.GlaccntConverter;
import src.services.gl.GlaccntModel;
import src.services.gl.JvModel;
import src.services.system.BranchModel;
import src.util.Constanta;
import src.util.Messager;
import src.util.Utils;
import src.view.security.LoginBean;

/**
 *
 * @author jay
 */
@ManagedBean
@SessionScoped
public class JvBean implements Serializable {

    private List<SelectItem> avblSource, avblBranch;
    private List<Glaccnt> availableGL;
    private Glaccnt unsaveGL;
    private Jv jv;
    private Jvdet unsaveDetail;
    private JvModel helper;    
    private CRUEDService csHelper;
    private BigDecimal sumDebet = BigDecimal.ZERO, sumCredit = BigDecimal.ZERO;
    private Users users;      
    private Integer branchId, jvdetIdx; //glaccntId
    private boolean editMode = false, editDetailMode=true, insertionMode=false, posted=true;

    public JvBean() {
        ambilUser();
        this.helper = new JvModel();
        this.csHelper = new CRUEDService();
        this.avblSource = Constanta.getJVType();
        
        this.availableGL = GlaccntConverter.glaccountDB;
        
        newData();
        editMode=false;
    }
    
    private boolean cekConfig() {
        boolean complete=true;
        this.branchId = users.getBranch().getBranchId();
        if (this.branchId==null) complete=false;
        if(complete==false) Messager.showWarning("unconfig");
        return complete;
    }
    
    public Jv getJv() {
        return jv;
    }

    public void setJv(Jv jv) {
        this.jv = jv;
    }

    public List<Glaccnt> getAvailableGL() {
        return availableGL;
    }

    public void setAvailableGL(List<Glaccnt> availableGL) {
        this.availableGL = availableGL;
    }

    public Jvdet getUnsaveDetail() {
        return unsaveDetail;
    }

    public void setUnsaveDetail(Jvdet unsaveDetail) {
        this.unsaveDetail = unsaveDetail;
    }

    public boolean isEditMode() {
        return editMode;
    }

    public List<SelectItem> getAvblSource() {
        return avblSource;
    }

    public List<SelectItem> getAvblBranch() {
        return avblBranch;
    }

    public BigDecimal getSumCredit() {
        return sumCredit;
    }

    public BigDecimal getSumDebet() {
        return sumDebet;
    }
  
    private void removeEmptyRow(){
        for(int i = 0; i<jv.getJvdets().size(); i++){
           Integer id = jv.getJvdets().get(i).getGlaccntId();
           if(id==null) {
               jv.getJvdets().remove(i);
               i--;
           }
        }
    }
    
    private void initForm() {
        this.availableGL = GlaccntConverter.glaccountDB;
        this.avblBranch = new BranchModel().listAll();
        this.editMode = true;
        this.posted = true;
    }
        
    //@PostConstruct
    public final void newData() { 
        initForm();
        cekConfig();
        if (this.jv!=null) jv = null;
        this.jv = new Jv();
        this.jv.getJvdets().add(new Jvdet());    
        this.jv.setBranchId(branchId);
        this.jv.setUserId(users.getUserId());
        this.unsaveGL = new Glaccnt();
        insertionMode = true;
    }
    
    public void openData() {
        initForm();
        insertionMode = false;
    }
        
    public void handleRemoveDetail() {  
        if (jv.getJvdets().size() == 1) jv.getJvdets().add(new Jvdet());
        sumJV();
    }  
    
    public void initCredit() {  
        if (unsaveDetail.getDebit() != null) {
            if (unsaveDetail.getDebit().compareTo(BigDecimal.ZERO) > 0) 
                unsaveDetail.setCredit(BigDecimal.ZERO);
        }
    }
    
    public void initDebit() {  
        if (unsaveDetail.getCredit() != null) {
            if (unsaveDetail.getCredit().compareTo(BigDecimal.ZERO) > 0) 
            unsaveDetail.setDebit(BigDecimal.ZERO);
        }    
    }
    
    public void newDetail() {
        this.unsaveDetail = new Jvdet();
        this.unsaveGL = new Glaccnt();//Model().getById(396);//new Glaccnt();
        editDetailMode = false;
    }
    
    public void editDetail(Jvdet data) {
        this.jvdetIdx = jv.getJvdets().indexOf(data);
        //this.glaccntId = data.getGlaccntId();
        this.unsaveDetail = Jvdet.clone(data);
        this.unsaveGL = new GlaccntModel().getById(unsaveDetail.getGlaccntId());
        this.editDetailMode = true;
    }
    
    public void saveDetail() {
        boolean success=true;
        try {
            unsaveDetail.setGlaccntId(unsaveGL.getGlaccntId());
            if(!editDetailMode) {
                this.jv.getJvdets().add(unsaveDetail);
                removeEmptyRow();
                
            } else this.jv.getJvdets().set(jvdetIdx, Jvdet.clone(unsaveDetail));
            sumJV();
            
        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    public String selectItemValueOf(Integer id) {
        //return (String) Utils.selectItemValueOf(availableGL, id);
        if (id!=null && !id.equals(0)) {
            int idx=0;
            boolean found=false;
            while (idx<availableGL.size() && !found) {
                Glaccnt it = availableGL.get(idx);
                found = id.equals(it.getGlaccntId()) ? true:false;
                if (found) return it.getAccountName();
                idx++;
            }
        }
        return null;
    }
    
    private void sumJV() {
        sumDebet = BigDecimal.ZERO;
        sumCredit = BigDecimal.ZERO;
        for(int i = 0; i<jv.getJvdets().size(); i++){
           sumCredit = sumCredit.add(jv.getJvdets().get(i).getDebit());
           sumDebet = sumDebet.add(jv.getJvdets().get(i).getCredit());
        }
    }
    
    private String newNumber() {
        String no = null;
        
        if (jv.getBranchId() != null) {
            Numbering currentNo = csHelper.getNextTrxNumber(8, jv.getBranchId(), 0, 1);
            no=currentNo.getTrxNum();
        }
        return no;
    }
     
    private String userLog(){
        return Utils.logActions(users.getUserName(), jv.getJvDate());
    }
    
    private void save() {
      
        if (cekConfig()==true) {
            jv.setLogCreate(userLog());
                
            //String log
            removeEmptyRow();
            jv.setPosted(false);
            jv.setJvSource(Constanta.JV_JU);
            jv.setJvdets(jv.getJvdets());
            jv.setJvNo(newNumber());

            boolean success = helper.saveData(jv);

            // re-insert
            if (!success && insertionMode) jv.setJvId(null);
            else insertionMode = false;

            editMode = !success;        
            posted  = !success;
            Messager.showSaveUpdateStatus(success);     
        }
    }
    
    public void trySave() {
        if (sumDebet.compareTo(BigDecimal.ZERO)==0) Messager.showError("jvEmpety");
        else if (sumCredit.compareTo(sumDebet)==0) save();
        else Messager.showError("jvAmountInvalid");
    }
    
    public void posting() {
        jv.setLogPost(userLog());
        jv.setPosted(true);
        boolean success = helper.saveData(jv);
        editMode = !success;
        posted=success;
        if (success) {
            jv = null;
            jv = new Jv();
        }
        Messager.showDeleteStatus(success);     
    }
    
    public void delete() {
        jv.getJvdets().clear();
        jv.setJvdets(jv.getJvdets());
        
        boolean success = helper.deleteData(jv);
        editMode = !success;
        if (success) {
            jv = null;
            jv = new Jv();
        }
        Messager.showDeleteStatus(success);     
    }

    public boolean isPosted() {
        return posted;
    }
        
    private void ambilUser() {
        FacesContext context = FacesContext.getCurrentInstance();
        LoginBean logBean = (LoginBean) context.getApplication().evaluateExpressionGet(context, "#{loginBean}", LoginBean.class);
        this.users = logBean.getSelectedUser();
    }

    public Glaccnt getUnsaveGL() {
        return unsaveGL;
    }

    public void setUnsaveGL(Glaccnt unsaveGL) {
        this.unsaveGL = unsaveGL;
    }
    
    public List<Glaccnt> completeGL(String query) {  
        List<Glaccnt> suggestions = new ArrayList<>();  
        String q = query.trim();
        for(Glaccnt gl : availableGL) {  
            if(gl.getAccountNo().startsWith(q) || gl.getAccountName().toLowerCase().startsWith(q.toLowerCase()))
                suggestions.add(gl);  
        }  
        return suggestions;  
    }  
}
